import re
import os
import sys
from xml.etree.ElementTree import ElementTree, Element

class Unit(object):
    def __init__(self, path):
        self.path = path
        self.uses_interface = []
        self.uses_implementation = []

    def parse(self):
        f = open(self.path)
        try:
            content = ''.join(f.readlines())
        finally:
            f.close()

        m = re.findall(r'uses([\w\s,\.\n]+);', content, re.MULTILINE)

        f = lambda x: [u.lower() for u in re.findall(r'([\w.]+)', x)]
        if m:
            self.uses_interface = f(m[0])
            self.uses_implementation = (len(m)==2) and f(m[1]) or []

    def _get_name(self):
        return '.'.join(os.path.basename(self.path).split('.')[:-1])

    name = property(_get_name)


class Network(object):
    def __init__(self, name):
        self.graph = []
        self.name = name

    def add(self, source, destination):
        if type(destination) == list:
            for d in destination:
                self.graph.append((source, d,))
        else:
            self.graph.append((source, destination))

    def get_source_nodes(self):
        return set([g[0] for g in self.graph])

    def get_destination_nodes(self):
        return set([g[1] for g in self.graph])

    def get_node_list(self):
        return self.get_source_nodes().union(self.get_destination_nodes())


class MetaNetWork(object):
    def __init__(self):
        self.interface = Network('interface')
        self.implementation = Network('implementation')
        self.redes = [self.interface, self.implementation,]

    def get_node_list(self):
        nodes = self.interface.get_node_list()
        nodes.union(self.implementation.get_node_list())
        return nodes

def addUnits(meta, dirname, files):
    #print meta, dirname, files
    for file in files:
        if file.split('.')[-1] in ['pas']:
            u = Unit(os.path.join(dirname, file))
            u.parse()

            badlist = ['windows', 'messages', 'sysutils', 'variants', 'classes', 'graphics', 
                'controls', 'forms', 'db', 'adodb', 'testextensions', 'inifiles', 'dbclient',
                'contnrs', 'specifiers','xmltestrunner', 'generics.collections', 'sistema.comum', 
                'dialogs', 'stdctrls', 'extctrls', 'rzpanel',]
                
            acept = lambda x: (x not in badlist) and \
                (not x.startswith('suporte.')) and \
                (not x.startswith('sistema.')) and \
                (not x.startswith('fachada.'))
            meta.interface.add(u.name, [unit for unit in u.uses_interface if acept(unit)])
            meta.implementation.add(u.name, [unit for unit in u.uses_implementation if acept(unit)])

        #print 'Nome: %s\nUnit: %s\nInterface: %s\nImplementation: %s\n\n' % (u.name, u.path, u.uses_interface, u.uses_implementation,)

if __name__ == '__main__':
    #print 'Obtendo metarede'
    meta = MetaNetWork()
    try:
        dirname = sys.argv[1]
    except:
        dirname = '.'

    #dirname = r'D:\Projetos\Esys\SourceDepencies\classes'

    os.path.walk(dirname, addUnits, meta)

    root = Element('DynamicNetwork')
    metaMat = Element('MetaMatrix')
    nodes = Element('nodes')
    networks = Element('networks')

    root.append(metaMat)
    metaMat.append(nodes)
    metaMat.append(networks)

    ns_units = Element('nodeset', id='units', type='resource')
    nodes.append(ns_units)

    for node in meta.get_node_list():
        n = Element('node', id=node)
        ns_units.append(n)
        subsistema = node.split('.')
        props = Element('properties')
        n.append(props)
        props.append( Element('property', name='subsistema', type='string', value=subsistema[0]) )

    for n in meta.redes:
        graph = Element('graph',
                    id=n.name,
                    targetType='resource',
                    sourceType='resource',
                    isDirected='true')

        for g in n.graph:
            e = Element('edge',
                        source=g[0],
                        target=g[1],
                        type='binary',
                        value='1')
            graph.append(e)

        networks.append(graph)

    ElementTree(root).write(sys.stdout)
